package com.ctrip.demo.leetcode;

import java.util.Arrays;

public class HeapSort {

    public static void main(String[] args) {
        heapSort(new int[]{2,1,5,2,4,6,3});
    }

    public static void heapSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        int len = arr.length;
        // 构建大顶堆，
        buildMaxHeap(arr, len);
        System.out.println(Arrays.toString(arr));
        // 交换堆顶和当前末尾节点，重置大顶堆
        for (int i = len - 1; i > 0; i--) {
            swap(arr, 0, i);
            len --;
            heapify(arr, 0, len);
        }
        System.out.println(Arrays.toString(arr));
    }

    public static void buildMaxHeap(int[] arr, int len) {
        for (int i = (int) (Math.floor(len / 2) - 1); i >= 0 ; i--) {
            // 从最后一个非叶子节点开始向前遍历，调整节点性质，使之成为大顶堆。
            heapify(arr, i, len);

        }
    }

    private static void heapify(int[] arr, int i, int len) {
        // 根据堆性质，找出它左右节点的索引
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        // 默认当前节点（父节点）最大值
        int largestIndex = i;

        if (left < len && arr[left] > arr[largestIndex]) {
            // 如果有左节点，并且左节点的值更大，更新最大值的索引
            largestIndex = left;
        }

        if (right < len && arr[right] > arr[largestIndex]) {
            // 如果右节点，并且右节点的值更大，更新最大值的索引
            largestIndex = right;
        }

        if (largestIndex != i) {
            // 如果最大值不是当前非叶子节点的值，那么就把当前节点的最大值的子节点值互换
            swap(arr, i, largestIndex);
            // 因为互换之后，子节点值变了，如果该子节点也有自己的子节点，需要再次调整
            heapify(arr, largestIndex, len);
        }
    }

    private static void swap (int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}
